home *** CD-ROM | disk | FTP | other *** search
- ;************************************************************************
- ;* *
- ;* TPLAS.ASM - Generate a Plasma fractal of 320x200 dimensions *
- ;* and display on screen. *
- ;* *
- ;* This is a working prototype of what will become TomsPlas. At *
- ;* that point, the fractal will be twice the size of the screen *
- ;* (640x480), allowing greater movement in the window, and the *
- ;* window will be expanded to much more of the screen (perhaps *
- ;* all?). Controls will be added to vary the speed (1-9 the *
- ;* number of frames to skip to speed it up, +/- a delay factor.) *
- ;* The code itself will be optimized to eliminate repetitive *
- ;* code, such as a push right before a pop, from the macros. *
- ;* Also, the movement and palette generation routines should *
- ;* be moved into the function itself rather than in the data *
- ;* file. This would shrink the data file to exactly 65,536 *
- ;* bytes, all of which would be numbers for the random series. *
- ;* *
- ;* All code and original algorithms expressed herein, *
- ;* Copyright (C) 1994 by Tom Dibble *
- ;************************************************************************
-
-
- .MODEL TINY ; always must be TINY model for .COM ...
-
- LOCALS
-
- ;<<Macros>>
-
- Screen_MaxX equ 320
- Screen_MaxY equ 240
-
-
- ; PrintNum(n)
- ; Print a decimal number to the screen using DBuf and INT 21h:09h
- ; Prints number up to 1000
- PrintNum MACRO n
- LOCAL @@PosNum
- push ax
- push bx
- push cx
- push dx
- push di
-
- xor bx,bx
- mov di,offset DBuf
-
- mov ax,n
- cmp ax,0
- jg @@PosNum
- neg ax
- mov [di+0], BYTE PTR '-'
- inc bx
-
- @@PosNum:
- xor dx,dx
- mov cx,1000
- div cx
- add ax,48 ; convert whole # to ASCII
- mov [di+bx],al
- inc bx
- mov ax,dx ; put remainder in ax
-
- xor dx,dx
- mov cx,100
- div cx
- add ax,48 ; convert whole # to ASCII
- mov [di+bx],al
- inc bx
- mov ax,dx ; put remainder in ax
-
- xor dx,dx
- mov cx,10
- div cx
- add ax,48 ; convert whole # to ASCII
- mov [di+bx],al
- inc bx
- mov ax,dx ; put remainder in ax
- add ax,48 ; convert whole # to ASCII
- mov [di+bx],al
- inc bx
- mov ax,dx ; put remainder in ax
- inc bx
- mov [di+bx], BYTE PTR 10 ; CR
- inc bx
- mov [di+bx], BYTE PTR 13 ; LF
- inc bx
- mov [di+bx], BYTE PTR '$' ; terminate string
-
- mov ah,09h
- mov dx,offset DBuf
- int 21h
- pop di
- pop dx
- pop bx
- pop cx
- pop ax
- endm
-
-
- ; GetPoint(x,y)
- ; Get the point in DS:[plasma] and place it in AL
- ; x and y can not be any of the following: AX, BX, CX
- GetPoint MACRO x,y
- push bx ; So we have some regs to play with
- push cx ;
- push ds
-
- mov bx, y
- mov cx, bx ; multiply by (320) [256+64 == <<8 + <<6]
- xchg bh, bl ;
- shl cx, 6 ;
- add bx, cx ;
- add bx, x
- mov ds, [Plasma] ; DS --> (0,0) in Plasma mem block
- mov al, [bx] ; Get the damned byte
-
- pop ds
- pop cx
- pop bx
- endm
-
-
- ; SetPoint(x,y)
- ; Set the point in DS:[plasma] to value in AL
- SetPoint MACRO x,y
- push bx ; So we have some regs to play with
- push cx ;
- push ds
-
- mov bx, y
- mov cx, bx ; multiply by (320) [256+64 == <<8 + <<6]
- xchg bh, bl ; (mov low into high, same as shl bx, 8)
- shl cx, 6 ;
- add bx, cx ;
- add bx, x
- mov ds, [Plasma] ; DS --> (0,0) in Plasma mem block
- mov [bx], al ; Set the damned byte
- pop ds ; DS --> Data
- push ds
- mov ds, [Video] ; DS --> Video mem block
- mov [bx], al ; Put this bitch on screen!
-
- pop ds
- pop cx
- pop bx
- endm
-
-
- ; SubDivide x1, y1, x2, y2
- ; Subdivide a Plasma rectangle defined by given coordinates and recurse.
- SubDivide MACRO x1,y1,x2,y2
- mov ax,y2
- push ax
- mov ax,x2
- push ax
- mov ax,y1
- push ax
- mov ax,x1
- push ax
- call SubDiv
- endm
-
- ; Adjust x1, y1, x2, y2, xm, ym
- ; Adjust point (x,ym) to average of (x,y1) and (x,y2) plus a random val.
- ;
- Adjust MACRO x1, y1, x2, y2, xm, ym
- mov ax, ym
- push ax
- mov ax, xm
- push ax
- mov ax, y2
- push ax
- mov ax, x2
- push ax
- mov ax, y1
- push ax
- mov ax, x1
- push ax
-
- call Adj
-
- endm
-
-
- ; Rand8
- ; Get the next 8-bit random value from Rand_Series. Put it into AL.
- Rand8 MACRO
- push ds
- mov bx, Rand_Ptr
- mov ds, [Rand_Series]
- mov al, [bx]
- pop ds
- inc Rand_Ptr
- endm
-
- ; Rand16
- ; Get the next 16-bit random value from Rand_Series. Put it into AX.
- Rand16 MACRO
- push ds
- mov bx, Rand_Ptr
- mov ds, [Rand_Series]
- mov ax, [bx]
- pop ds
- inc Rand_Ptr
- inc Rand_Ptr
- endm
-
-
- ; GetTRand
- ; Get System-Time 'seconds' and '1/100 seconds' into DH and DL, respectively
- ; 'hour' and 'minute' into CH and CL, respectively
- GetTRand MACRO
- push ax
- mov ah, 2Ch ; DOS Interrupt Fn: 'Get System Time'
- int 21h
- pop ax
- endm
-
-
- ; malloc: allocate memory to program in 16-byte chunks
- ; 'amount' is the number of 'paragraphs' to allocate
- ; (a paragraph being 16 bytes).
- ; CF set on error, AX is 09h, BX is size of largest block
- ; The segment address is left in AX if successful
- malloc MACRO amount
- mov ah,48h
- mov bx,amount
- int 21h
- endm
-
- ; mfree: frees malloc'd memory.
- mfree MACRO where
- mov ah,49h
- mov es,where
- int 21h
- endm
-
-
- ; keyp: check for key press
- ; CF set if key is present.
- keyp MACRO
- mov ah,0bh
- int 21h
- or al,al
- endm
-
- ; kwait: wait for key-press
- kwait MACRO
- push ax
- mov ah, 08h
- int 21h
- pop ax
- endm
-
- ; exit: exit with error code
- exit MACRO return_code
- mov al,return_code
- mov ah,4ch
- int 21h
- endm
-
- ; prints: print a string to text screen
- prints MACRO str
- mov ah,09h
- mov dx,offset str
- int 21h
- endm
-
-
- ; fopen: open a file for read (0) or write (1) or both (2)
- ; CF set on error, AX holds error code.
- ; file handle left in AX if successful.
- fopen macro file,attrib
- mov ah,3dh
- mov al,attrib
- mov dx,offset file
- int 21h
- endm
-
-
- ; fread: read information from file opened by fopen.
- ; Data read into (AX:00h).
- ; CF set on error.
- ; AX return (number of bytes read) is nuked.
- fread macro handle,bytes
- push ax
- push ds
- push ax
- mov ah,3fh
- mov bx,[handle]
- mov cx,bytes
- xor dx,dx ; Segment is (00h)
- pop ds ; this used to be AX!
- int 21h
- pop ds
- pop ax
- endm
-
-
-
-
- ;**************************** << CODE SEGMENT >> ****************************;
-
- .CODE
-
- org 100h
- start: jmp begin
-
- ; Variables
- ; Strings
- CopyRight db "Tom's Plasma (C) 1994 by Tom Dibble",10,13,"$"
- TPVersion db "Revision 1.1, March 19, 1994",10,13,"$"
- NoMemory db "Out of Base Memory!",10,13,"$"
- NoFile db 10,13,\
- "ERROR: Couldn't open TomsPlas.DAT!",10,13,\
- " Change to the directory containing",10,13,\
- " TomsPlas.DAT and restart the program!",10,13,"$"
- DebugPoint db "Debug Point!",10,13,"$"
- DataFile db "TOMSPLASM.DAT",0
- DBuf db 80 dup (?)
-
- ; General Variables
- OrigVMode db 03h ; Mode the video card was in when we got here!
- recadj db 11111111B ; last 8 bits set (255)
- count dw 0 ; loop counter while swimmin' and cyclin'
- DATHandle dw ? ; Handle to Data File
- Rand_Ptr dw ? ; Pointer to next random value in [Rand_Series]
- WinHide db 0 ; Is the swim-window hidden?
-
- ; Segment Addresses
- Plasma dw 0 ; Segment beginning for Plasma Bitmap
- Video dw 0 ; Segment beginning for Video Memory
- Color dw 0 ; Segment for Color-Palette Data
- Movement dw 0 ; Movement data
- Rand_Series dw 0 ; 64k of random values
-
- ASSUME CS:@code,DS:@code,ES:@code
-
- .386 ; select the processor
-
- begin: ; from here on in is executable stuffs ...
-
- mov sp,offset stacktop ; set new stack
-
- mov bx,last_inst-start+100h ; (size of prog. + 100h header)
- shr bx,4 ; shrink memory usage to program size
- inc bx ; in pages (16 bytes)
- mov ah,4ah
- int 21h ; ES segment is resized. ES is set to @code
-
- prints CopyRight ; display header message
- prints TPVersion ; display header message, part 2
-
-
- ; InitProgram sets video mode, allocates memory, seeds 'Random'
- CALL InitProgram
-
- ; GenPlasma does all the work
- mov [recadj], 11111111B ; last eight bits default ('Rough')
- CALL ClearPlasma
- NewPlasma:
- CALL ShowPlasma
- CALL ClearPlasma
- CALL GenPlasma
-
- ; Cycle the colors and swim the image
- ContinueCycle:
- cmp [WinHide],0
- jne NoWindow
- CALL CycleSwim
- jmp KeyDecipher
- NoWindow:
- CALL ShowPlasma
- CALL CycleNoSwim
-
- KeyDecipher:
- ; Wait for a key to be pressed (if none has already)
- mov ah, 08h
- int 21h
- ; Process that key!
- cmp al, 13 ; Return --> New Plasma!
- je NewPlasma
- cmp al, ' ' ; Space --> Hide Window!
- je ToggleWindow
- cmp al, '1' ; New Plasma, recadj of 255
- je RoughPlasma
- cmp al, '2' ; New Plasma, recadj of 127
- je MedPlasma
- cmp al, '3' ; New Plasma, recadj of 63
- je SmoothPlasma
- cmp al,27 ; <Esc> --> Get outta here!
- je LeaveProg
-
- jmp ContinueCycle
-
- ToggleWindow:
- not [WinHide]
- jmp ContinueCycle ; any key puts the window back!
-
- RoughPlasma:
- mov recadj, 11111111B
- jmp NewPlasma
-
- MedPlasma:
- mov recadj, 01111111B
- jmp NewPlasma
-
- SmoothPlasma:
- mov recadj, 00111111B
- jmp NewPlasma
-
- LeaveProg:
-
- ; Clean out memory allocated, return to right video mode
- CALL CleanUp
-
- ;Now exit to DOS
- mov ah,4Ch
- int 21h
- ret
-
- ;************************************************************************
- ;* *
- ;* InitProgram *
- ;* *
- ;* Allocate memory to Plasma, clear it out *
- ;* Open Data File *
- ;* Allocate memory to Movement, read *
- ;* Allocate memory to Color, read *
- ;* Allocate memory to Rand_Series, read *
- ;* Get Rand_Ptr from system time function *
- ;* Set Video Mode to 13 *
- ;* *
- ;************************************************************************
-
- InitProgram PROC NEAR
- malloc 4000+1 ; allocate memory for plasma buffer + 1 para.
- jc nomem ; break if not enough memory
- mov [Plasma],ax ; store address
-
- malloc 2500+1 ; allocate memory for movement buffer + 1
- jc nomem ; as above...
- mov [Movement],ax
- malloc 192+1 ; allocate memory for color buffer + 1
- jc nomem
- mov [Color],ax
- malloc 1000h ; allocate memory for random buffer + 1
- jc nomem
- mov [Rand_Series],ax
- jmp allocok ; skip the following
-
- allocok: fopen DataFile,0 ; open TomsPlas.DAT read only
- jnc loadok ;
- prints NoFile ; You schmuck! It's not here!
- mfree [Plasma]
- mfree [Movement]
- mfree [Color]
- mfree [Rand_Series]
- exit 254 ; so quit
- loadok: mov [DATHandle],ax ; store handle
-
- mov ax,[Movement] ; read movement data
- fread DATHandle,40000
- mov ax,[Color] ; color data
- fread DATHandle,3072
- mov ax,[Rand_Series] ; and random series
- fread DATHandle,0ffffh
-
- GetTRand ; get 'time' values into CX and DX
- add cx, dx ; accumulate values
- mov Rand_Ptr, cx ; put Rand_Ptr as a random place in series
-
- mov ax,0F00h ; get the video mode now
- int 10h ;
- mov [OrigVMode], al
- mov ax,0013h ; set video mode 13
- int 10h
- mov [Video],0a000h ; Start segment for Video Mem
-
- mov si, 0
- mov cx, 3*255 ; Set Color Palette!
- push ds ;
- mov ds, [Color]
- cld
- mov dx, 03C8h ;
- mov al, 1 ; start with color '1'
- out dx, al ;
- inc dx
- rep outsb
- pop ds
-
- ret
-
- nomem:
- prints NoMemory
- exit -1
-
- InitProgram ENDP
-
- ClearPlasma PROC NEAR
- push eax ;
- push cx ;
- push es ; Clear out the memory devoted to
- push di ; the Plasma buffer so that
- ; we can create a new Plasma!
- mov ax, 0 ;
- shl eax, 16 ;
- mov ax,0 ;
- mov cx, [Plasma] ;
- mov es, cx ;
- mov di, 0 ;
- mov cx, 64000/4 ;
- rep stosd ; put eax into es:di
- ;
- pop di ;
- pop es ;
- pop cx ;
- pop eax ;
- ret
- ClearPlasma ENDP
-
-
- ShowPlasma PROC NEAR
- push ax
- push cx
- push es
- push ds
- push si
- push di
-
- mov si,0
- mov di,0
- mov ax,[Video]
- mov es,ax
- mov ds,[Plasma]
- mov cx, 320*200/4
- rep movsd
-
- pop di
- pop si
- pop ds
- pop es
- pop cx
- pop ax
- ret
- ShowPlasma ENDP
-
-
- CleanUp PROC NEAR
- push ax
-
- mfree [Plasma]
- mfree [Movement]
- mfree [Color]
- mfree [Rand_Series]
-
- mov ah,00h
- mov al,[OrigVMode] ; set video mode back to what it was
- int 10h
-
- prints CopyRight ; Tell 'em this again!
-
- pop ax
- ret
-
- CleanUp ENDP
-
-
- GenPlasma PROC NEAR
-
- Rand8
- SetPoint 0,0
- Rand8
- SetPoint 319, 199
- Rand8
- SetPoint 0, 199
- Rand8
- SetPoint 319, 0
-
- SubDivide 0,0,319,199
- ret
- GenPlasma ENDP
-
- ;************************************************************************
- ;* *
- ;* SubDiv x1, y1, x2, y2 *
- ;* *
- ;* Corners have already been set to proper values. *
- ;* Check each side if it has been set yet, and if not, *
- ;* set it to the average of associated corners plus *
- ;* a random value based on Code:recadj. *
- ;* Set middle to average of four sides. *
- ;* Recurse for each of four sectors in lt,rt,rb,lb order. *
- ;* Free up our memory and get the hell outta here! *
- ;* *
- ;* 18 bytes on stack per recursion, times 7 recursions. Stack *
- ;* size must be large enough to handle this load! *
- ;* *
- ;************************************************************************
-
-
- SubDiv PROC
- ARG x1:word, y1:word, x2:word, y2:word
- LOCAL x:word, y:word=LocalStk
- push bp
- mov bp,sp
- sub sp,LocalStk ; Set-up local stack
- push cx
- push dx
-
- ; First, check for recursion halts.
- ; < if(xhalt && yhalt) return >
-
- mov ax,[x1]
- add ax,[x2]
- shr ax,1 ; divide by two for average of x1,x2
- mov [x],ax ; now 'x' is on stack!
-
- ; Find the 'y' value now!
- mov cx,[y1]
- add cx,[y2]
- shr cx,1 ; divide by two for average of y1,y2
- mov [y],cx ; now 'y' is on stack!
-
- cmp ax,[x1]
- jg xchecks ; if x1 != x, keep on going
- ; x does not check.
- ; Check for 'y' value recursion halt.
- cmp cx,[y1]
- jg ychecks ; y checks. Jump out.
-
- pop dx ; Cleanup: return DX, to it's place
- pop cx ; and same with CX, SP and BP ...
- mov sp,bp ;
- pop bp ;
- ret 8
-
- xchecks:
- ychecks:
-
- ; Okay! We have checked for recursion halt
- ; and have calculated x and y.
- ; Next, check each of the four sides for empty
- ; and call 'Adjust' if so. Meanwhile, keep
- ; a running total of all the four sides so we
- ; can do a quick average of them in the next
- ; step.
-
- GetPoint [x],[y1]
- cmp al,0
- jne topgood
- Adjust [x1],[y1],[x2],[y1],[x],[y1]
- topgood:
- mov ah,0
- push ax
-
- GetPoint [x2],[y]
- cmp al,0
- jne rightgood
- Adjust [x2],[y1],[x2],[y2],[x2],[y]
- rightgood:
- mov ah,0
- pop bx
- add ax,bx
- push ax
-
- GetPoint [x],[y2]
- cmp al,0
- jne bottomgood
- Adjust [x1],[y2],[x2],[y2],[x],[y2]
- bottomgood:
- mov ah,0
- pop bx
- add ax,bx
- push ax
-
- GetPoint [x1],[y]
- cmp al,0
- jne leftgood
- Adjust [x1],[y1],[x1],[y2],[x1],[y]
- leftgood:
- mov ah,0
- pop cx
- add cx,ax
- ; No push of AX here!
-
- ; Okay. All four side pixels have been computed
- ; and plotted on the screen and in memory. AX
- ; holds the sum of all four pixels. Divide by four
- ; and set x,y to the resulting value.
- shr cx,2
-
- mov al,cl
- SetPoint [x],[y]
-
- ; Finally. All the real work is done. Now, decrease
- ; the recurse-level adjustment and recurse down
- ; to the next level for each of the four quads
-
- mov al, recadj
- push ax
- shr al, 1
- mov recadj, al
-
- SubDivide [x1], [y1], [x], [y]
- SubDivide [x], [y1], [x2], [y]
- SubDivide [x], [y], [x2], [y2]
- SubDivide [x1], [y], [x], [y2]
-
- pop ax
- mov recadj, al ; return it to what it was before we got here.
-
- pop dx ; Cleanup: return DX, to it's place
- pop cx ; and same with CX, SP and BP ...
- mov sp,bp ;
- pop bp ;
- ret 8
- SubDiv ENDP
-
-
- ;************************************************************************
- ;* *
- ;* Adj x1, y1, x2, y2, x, y *
- ;* *
- ;* Sets the point at (x,y) to be the average of points (x1,y1) *
- ;* and (x2,y2), plus a random factor based on recval. *
- ;* *
- ;* Get points (1) and (2) into AH, AL. *
- ;* Average the values into AL. *
- ;* CBW AL, move into BX. *
- ;* Get a random 16-bit number into AX *
- ;* Multiply AX and recval. *
- ;* Shift DX to the right 2 bits (same as shifting 32-bit 18) *
- ;* Move DX into AX *
- ;* Add BX into AX *
- ;* if AX < 1, AX = 1. *
- ;* if AH != 0, AL = 255 *
- ;* Set point (x,y) to value in AL. *
- ;* *
- ;************************************************************************
-
- Adj PROC NEAR
- ARG x1:word, y1:word, x2:word, y2:word, xm:word, ym:word
- push bp
- mov bp, sp
- push bx
- push cx
- push dx
-
- mov ah,0
-
- GetPoint [x1], [y1] ; Sets 'AL'
- mov cl, al ; Put it into 'CL'
-
- GetPoint [x2], [y2] ; Sets 'AL'
- add cx, ax ; Add this guy to the first.
-
- shr cx, 1 ; Divide by two (to make average)
-
- Rand8 ; random byte in al
- mov bl, recadj
- and al, bl ; restrict the rand #
- shr bl, 1 ; div by 2
- sub al, bl ; subtract 1/2 (so low # neg, high pos)
- cbw
- add ax, cx ; cx is pos. ax may be + or -
- ; If the sum exceeded 255, ah will
- ; have a positive number in it.
- ; If the sum was less than zero, ax
- ; will be negative.
-
- cmp ax,0
- jg AdjLowCheck
- mov ax,1 ; ax < 0, force it to lower bound!
- jmp AdjSetPoint
-
- AdjLowCheck:
- cmp ax,256
- jl AdjSetPoint
- mov ax,255 ; ax > 255, force it to upper bound!
-
- AdjSetPoint:
- SetPoint [xm], [ym]; Set (x,y) to 'AL'
-
- pop dx
- pop cx
- pop bx
- pop bp
-
- ret 12 ; 6*2 parameters
-
- Adj ENDP
-
-
-
-
- ;************************************************************************
- ;* *
- ;* CycleSwim *
- ;* *
- ;* Cycle the color palette and swim a middle window of plasma. *
- ;* *
- ;* 'Swimming' is the process of adding two sections of the *
- ;* plasma fractal together, then moving the pointers *
- ;* to each of those sections in a loop so as to create *
- ;* a composite, changing fractal. *
- ;* *
- ;************************************************************************
-
-
- CycleSwim PROC NEAR
-
- mov ax, [Video] ; Put the video segment address in es
- mov es, ax ; for stosd loop below.
-
- mainloop:
- ; We'll do all this setup stuff *BEFORE* we wait for VRT.
- ; This sets things up for :setpl: loop below ...
-
- ; Rotate the palette!
- push ds
- push es
- cld
- mov es, [Color]
- mov ds, [Color]
- mov bx, 0
-
- mov ax, [bx] ; r,g of color[0]
- mov dl, [bx+2] ; b of color[0]
-
- mov cx, 256*3 ; loop 256*4*3/4 times
- mov si, 3
- mov di, 0
- rep movsd ; move bytes from ds:si to es:di
-
- mov bx, 256*4*3-3 ; copy saved rgb to end of current pal.
- mov [bx],ax
- mov [bx+2],dl
-
- pop es
- pop ds
-
- mov si,0
- mov cx,255*3 ; loop 255 times (for 255 DAC's)
- push ds
- mov ds,[Color] ; address segment
- cld ; ensure SI is incremented
-
- VSync:
- mov dx,03dah ; VGA input status register 1
- in al,dx ; load value
- test al,08 ; vertical retrace??
- je VSync ; if not, try again...
-
- ; Load all the info from the colour segment
- ; into the DAC's ...
-
- ; NOW do the final prep for color loading
- mov dx,3c8h ; DAC index register
- mov al,1 ; start with color 1
- out dx,al ; and load
- inc dx ; DAC read/write register
- rep outsb
-
- pop ds ; and restore DS back to code segment
-
- mov di,[count] ; source = count * 4
- shl di,2 ;
- push ds
- mov ds,[Movement] ; get segment address of movement data
- mov si,[di] ; load point 1, start of reading x-data
- mov bx,[di+2] ; load point 2, start of added x-data
- pop ds ; and restore DS back to code segment
- push ds
- mov ds,[Plasma] ; get segment of start of plasma
- mov di,320*50+90 ; put window in the center of the screen.
-
- mov ch,100 ; y loop = 100 pixels
- pl1: mov cl,40 ; x loop = 40 * 4 = 160 pixels
- pl2: lodsd ; get 4 source pixels from ds:si, inc si
- add eax,[si+bx] ; add 4 source pixels from ds:(si+bx)
- stosd ; and store them on screen to es:di, inc di
- dec cl ; dec x-counter
- jnz pl2 ; and loop..
-
- sub si,160 ; reset source to beg. of :pl1:
- mov dx,ds ; add 20 to DS :
- add dx,20 ; move 20*16 = 320 bytes down in source mem
- mov ds,dx
- add di,160 ; add 160 to vid ptr (to beg of next line)
- dec ch ; dec y-counter
- jnz pl1 ; and loop..
-
- pop ds ; and restore DS back to code segment
- inc word ptr [count] ; increase counter
- cmp word ptr [count],10000 ; reset it at end of cycle
- jne noreset
- mov word ptr [count],0
-
- noreset:
- keyp ; keypressed??
- jnz closedown ; if yes then quit..
- jmp mainloop
-
- closedown:
- ret
-
- CycleSwim ENDP
-
-
- ;************************************************************************
- ;* *
- ;* CycleNoSwim *
- ;* *
- ;* Just cycle the color palette. *
- ;* *
- ;************************************************************************
-
-
- CycleNoSwim PROC NEAR
-
- mov ax, [Video] ; Put the video segment address in es
- mov es, ax ; for stosd loop below.
-
- CNSmainloop:
- ; We'll do all this setup stuff *BEFORE* we wait for VRT.
- ; This sets things up for :setpl: loop below ...
-
- ; Rotate the palette!
- push ds
- push es
- cld
- mov es, [Color]
- mov ds, [Color]
- mov bx, 0
-
- mov ax, [bx] ; r,g of color[0]
- mov dl, [bx+2] ; b of color[0]
-
- mov cx, 256*3 ; loop 256*4*3/4 times
- mov si, 3
- mov di, 0
- rep movsd ; move bytes from ds:si to es:di
-
- mov bx, 256*4*3-3 ; copy saved rgb to end of current pal.
- mov [bx],ax
- mov [bx+2],dl
-
- pop es
- pop ds
- push ds
-
- mov si,0
- mov cx,255*3 ; loop 255 times (for 255 DAC's)
- mov ds,[Color] ; address segment
- cld ; ensure SI is incremented
-
- CNSVSync:
- mov dx,03dah ; VGA input status register 1
- in al,dx ; load value
- test al,08 ; vertical retrace??
- je CNSVSync ; if not, try again...
-
- ; Load all the info from the colour segment
- ; into the DAC's ...
-
- ; NOW do the final prep for color loading
- mov dx,3c8h ; DAC index register
- mov al,1 ; start with color 1
- out dx,al ; and load
- inc dx ; DAC read/write register
- rep outsb
-
- pop ds ; and restore DS back to code segment
-
- keyp ; keypressed??
- jnz leaveCNS ; if yes then quit..
- jmp CNSmainloop
-
- leaveCNS:
- ret
-
- CycleNoSwim ENDP
-
-
- mystack db 8192 dup (?) ; my stack: room for lots o' recursion
- stacktop equ $ ; top of my stack.
-
- last_inst: ; the end of the program!
-
- END start
-
-
-